package com.zmzncs.lmtc.module.park.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.zmzncs.lmtc.common.pojo.daoer.ParkingInfo;
import com.zmzncs.lmtc.common.pojo.tengda.CarTypes;
import com.zmzncs.lmtc.common.util.*;
import com.zmzncs.lmtc.common.interactive.miwang.MWPullData;
import com.zmzncs.lmtc.common.pojo.bolian.BoLianParkUpdateForm;
import com.zmzncs.lmtc.common.pojo.bolian.BolianQueryParkByIdRes;
import com.zmzncs.lmtc.common.pojo.bolian.QuoteField;
import com.zmzncs.lmtc.module.park.dao.BolianPullDao;
import com.zmzncs.lmtc.module.promotion.dao.MonthRulePullDao;
import com.zmzncs.lmtc.module.promotion.pojo.month_rule_pull.MonthRulePull;
import com.zmzncs.lmtc.module.park.pojo.park_info.*;
import com.zmzncs.lmtc.module.park.dao.ParkInfoDao;
import com.zmzncs.lmtc.module.park.service.ParkInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zmzncs.lmtc.module.promotion.service.MonthRulePullService;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

import static com.zmzncs.lmtc.common.util.BolianUtil.parkUnionId;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 任建波
 * @since 2020-09-29
 */
@Slf4j
@Service
public class ParkInfoServiceImpl extends ServiceImpl<ParkInfoDao, ParkInfo> implements ParkInfoService {

    @Autowired
    ParkInfoDao parkInfoDao;
    @Autowired
    MWPullData mwPullData;
    @Autowired
    BolianPullDao bolianPullDao;
    @Autowired
    MonthRulePullDao monthRulePullDao;
    @Autowired
    MonthRulePullService monthRulePullService;


    /**
     * 获取停车场列表
     */
    @Override
    public List<ParkInfoDTO> getParkList() {
        List<ParkInfoDTO> parkInfoDTOList = parkInfoDao.getParks();
        //  拼音首字母
        for (ParkInfoDTO park : parkInfoDTOList) {
            park.setParkNameFirstSpell(PingYinUtil.getPingYin(park.getParkName()).substring(0, 1).toUpperCase());
        }
        return parkInfoDTOList;
    }


    /**
     * 获取停车场分页列表
     */
    @Override
    public IPage<ParkInfoDTO> getParkPage(ParkInfoListForm form) {
        Page<Object> page = new Page<>(form.getCurrentPage(), form.getPageSize());
        IPage<ParkInfoDTO> iPage = parkInfoDao.getParkList(page, form);
        return iPage;
    }

    /**
     * 获取咪网停车场信息
     */
    @Override
    public ParkInfoDTO getParkingLotByCode(String partnerCode) {
        //获取咪网停车场信息
        ParkInfoDTO park = mwPullData.getMWPark(partnerCode);
        if (park != null) {
            //获取咪网停车场道闸通道信息
            mwPullData.getMWEntranceAndRoadWay(partnerCode, park.getBolianParkId());
            //获取咪网停车场月租车分组信息
            mwPullData.getMWMonthRule(partnerCode);

            //上传泊链停车场信息
            String addParkRestString = BolianUtil.addNewParkToBoLian(park.getBolianParkId(), park.getParkName(), park.getParkAddress(), park.getTelephone(),
                    park.getLongitude(), park.getLatitude(), park.getTotalParkSpace(), park.getEmptyParkSpace(), park.getPriceDesc());

            //上传泊链停车场信息 处理返回信息
            addBolianParkResult(park.getId(), addParkRestString);

            return park;
        }
        return null;
    }

    @Override
    public void updateParkToBolian(BoLianParkUpdateForm form) {
        //更新停车场信息到泊链
        String resultStr = BolianUtil.updateParkToBoLian(form.getParkId(), form.getType(), form.getTotalPlot(),
                form.getEmptyPlot(), form.getPriceDesc());

        if (StringUtils.isNotBlank(resultStr)) {
            JsonNode jsonNode = JsonUtil.getJsonNode(resultStr);
            String state = JsonUtil.getJsonValue(jsonNode, "state");
            String errmsg = JsonUtil.getJsonValue(jsonNode, "errmsg");
            if ("1".equals(state)) {
                log.info("停车场上传泊链成功:" + errmsg);
            } else {
                log.info("停车场上传泊链失败，原因：" + errmsg);
            }
        }
    }

    /**
     * 上传泊链停车场信息 处理返回信息
     */
    public void addBolianParkResult(Long parkId, String resultStr) {
        if (StringUtils.isNotBlank(resultStr)) {
            JsonNode jsonNode = JsonUtil.getJsonNode(resultStr);
            String state = JsonUtil.getJsonValue(jsonNode, "state");
            if ("1".equals(state)) {
                log.info("停车场上传泊链成功");
                String parkBolianId = JsonUtil.getJsonValue(jsonNode, "park_id"); //泊链车场编号
                String username = JsonUtil.getJsonValue(jsonNode, "username"); //车场登录账号
                String password = JsonUtil.getJsonValue(jsonNode, "password"); //车场登录密码
                ParkInfo parkInfo = new ParkInfo();
                parkInfo.setId(parkId);
                parkInfo.setBolianParkId(parkBolianId);
                parkInfo.setUsername(username);
                parkInfo.setPassword(password);
                parkInfo.setUpdateFromBolian(1);
                parkInfoDao.updateById(parkInfo);
            } else {
                String errmsg = JsonUtil.getJsonValue(jsonNode, "errmsg");
                ExceptionUtil.businessException("停车场上传泊链失败，原因：" + errmsg);
            }
        }
    }

    @Override
    public BolianQueryParkByIdRes getBolianParkInfo(String comId) {
        BolianQueryParkByIdRes bolianQueryParkByIdRes = BolianUtil.queryParkById(comId);
        return bolianQueryParkByIdRes;
    }

    @Override
    public void updateDateToParkInfo(String bolianComId, List<QuoteField> bolianPulls) {
        ParkInfoDTO park = parkInfoDao.getParkByBolianComId(bolianComId);
        if (park != null) {
            for (QuoteField field : bolianPulls) {
                if ("park_name".equals(field.getField())) {
                    park.setParkName(field.getNewValue());
                }
                if ("park_address".equals(field.getField())) {
                    park.setParkAddress(field.getNewValue());
                }
                if ("telephone".equals(field.getField())) {
                    park.setTelephone(field.getNewValue());
                }
                if ("longitude".equals(field.getField()) && "latitude".equals(field.getField())) {
                    park.setLongitude(field.getNewValue());
                    park.setLatitude(field.getNewValue());
                    String geoHashBinary = GeoHashUtil.getBinary(Double.parseDouble(park.getLongitude()), Double.parseDouble(park.getLatitude()), 32);
                    park.setGeohash(GeoHashUtil.getBase32(geoHashBinary));
                }
                if ("total_park_space".equals(field.getField())) {
                    park.setTotalParkSpace(Integer.valueOf(field.getNewValue()));
                }
                if ("empty_park_space".equals(field.getField())) {
                    park.setEmptyParkSpace(Integer.valueOf(field.getNewValue()));
                }
                if ("price_desc".equals(field.getField())) {
                    park.setPriceDesc(field.getNewValue());
                }
                if ("remark".equals(field.getField())) {
                    park.setRemark(field.getNewValue());
                }
                if ("bolian_park_union_id".equals(field.getField())) {
                    park.setBolianParkUnionId(field.getNewValue());
                }
                if ("bolian_park_id".equals(field.getField())) {
                    park.setBolianParkId(field.getNewValue());
                }
            }
            ParkInfo parkInfo = new ParkInfo();
            BeanUtils.copyProperties(park,parkInfo);
            parkInfoDao.updateById(parkInfo);
        } else {
            ExceptionUtil.businessException("引入字段的停车场不存在");
        }
    }

    @Override
    public void addParkInfo(ParkInfoAddFrom form) {
        int i = 0;
        ParkInfoDTO infoDTO = parkInfoDao.getParkByBolianComId(form.getBolianComId());
        if (infoDTO != null) {
            BeanUtils.copyProperties(form, infoDTO);
            infoDTO.setIsShow(1);
            infoDTO.setParkSource(1);
            infoDTO.setUpdateFromBolian(1);
            infoDTO.setReserveParkSpace(0);
            infoDTO.setSingleDoubleSystem(form.getSingleDoubleSystem());
            String geoHashBinary = GeoHashUtil.getBinary(Double.parseDouble(form.getLongitude()), Double.parseDouble(form.getLatitude()), 32);
            infoDTO.setGeohash(GeoHashUtil.getBase32(geoHashBinary));

            ParkInfo park = new ParkInfo();
            BeanUtils.copyProperties(infoDTO,park);
            i = parkInfoDao.updateById(park);
        } else {
            ParkInfoDTO parkInfoDTO = new ParkInfoDTO();
            BeanUtils.copyProperties(form, parkInfoDTO);
            Long parkInfoId = new SnowflakeIdUtil(new Random().nextInt(9), new Random().nextInt(9)).nextId();
            parkInfoDTO.setId(parkInfoId);
            parkInfoDTO.setIsShow(1);
            parkInfoDTO.setParkSource(1);
            parkInfoDTO.setUpdateFromBolian(1);
            parkInfoDTO.setReserveParkSpace(0);
            parkInfoDTO.setSingleDoubleSystem(form.getSingleDoubleSystem());

            String geoHashBinary = GeoHashUtil.getBinary(Double.parseDouble(form.getLongitude()), Double.parseDouble(form.getLatitude()), 32);
            parkInfoDTO.setGeohash(GeoHashUtil.getBase32(geoHashBinary));


            ParkInfo park = new ParkInfo();
            BeanUtils.copyProperties(parkInfoDTO,park);
            i = parkInfoDao.insert(park);
        }

        if (i > 0) {
            //根据泊链com_id更新状态(已引入）
            bolianPullDao.updateStatus(form.getBolianComId(), 2);
        }


    }

    @Override
    @Transactional
    public void addTengdaPark(TengdaParkAddForm form) {

        //根据泊链停车场Id查询停车场信息
        ParkInfoDTO parkInfo = parkInfoDao.getParkByBolianParkId(form.getParkId());
        if (parkInfo != null) {
            ExceptionUtil.businessException("该停车场已存在无需添加");
        }

        //添加订阅停车场，腾达项目订阅了主题后才能拉取停车场信息
        Boolean isSuccess = TengdaUtil.subscribe(form.getParkId());
        if (isSuccess) {
            ParkInfoDTO parkInfoDTO = new ParkInfoDTO();
            BeanUtils.copyProperties(form, parkInfoDTO);
            Long parkInfoId = new SnowflakeIdUtil(new Random().nextInt(9), new Random().nextInt(9)).nextId();
            parkInfoDTO.setId(parkInfoId);
            parkInfoDTO.setIsShow(1);
            parkInfoDTO.setParkSource(4);
            parkInfoDTO.setUpdateFromBolian(1);
            parkInfoDTO.setBolianParkUnionId(parkUnionId);
            parkInfoDTO.setBolianParkId(form.getParkId());
            parkInfoDTO.setIsAutopay(1);
            parkInfoDTO.setSingleDoubleSystem(1);
            parkInfoDTO.setEmptyParkSpace(form.getTotalParkSpace());
            String parkImagUrl = StringUtils.join(form.getParkImgUrl().toArray(), ',');
            parkInfoDTO.setParkImgUrl(parkImagUrl);

            String geoHashBinary = GeoHashUtil.getBinary(Double.parseDouble(form.getLongitude()), Double.parseDouble(form.getLatitude()), 32);
            parkInfoDTO.setGeohash(GeoHashUtil.getBase32(geoHashBinary));


            //上传泊链停车场信息
            parkToBolian(parkInfoDTO);

            ParkInfo park = new ParkInfo();
            BeanUtils.copyProperties(parkInfoDTO,park);
            parkInfoDao.insert(park);

            //拉取腾达停车场车辆类型信息
            getTengdaParkInfo(form.getParkId());
        }
}

    @Override
    public List<ParkInfoDTO> noManagerPark() {
        return parkInfoDao.noManagerPark();
    }

    @Override
    @Transactional
    public void getDaoErParkInfo(DaoerParkAddForm form) {

        ParkInfoDTO parkInfo = parkInfoDao.getParkByBolianParkId(form.getParkId());
        if (parkInfo != null) {
            ExceptionUtil.businessException("该停车场已存在，无需添加");
        }

        //道尔 获取停车场信息
        ParkingInfo parking = DaoerApiUtil.getParking(form.getParkId(),form.getAppName());
        if (parking == null || parking.getHead().getStatus().equals(0)) {
            ExceptionUtil.businessException("查询道尔停车场信息失败");
        }
        ParkingInfo.Body body = parking.getBody();

        ParkInfoDTO parkInfoDTO = new ParkInfoDTO();
        BeanUtils.copyProperties(form,parkInfoDTO);

        parkInfoDTO.setDaoerSecretKey(form.getAppName());
        parkInfoDTO.setEmptyParkSpace(form.getTotalParkSpace());
        parkInfoDTO.setParkSource(3);
        parkInfoDTO.setIsShow(1);
        parkInfoDTO.setIsAutopay(1);
        parkInfoDTO.setUpdateFromBolian(1);
        parkInfoDTO.setBolianParkId(form.getParkId());
        parkInfoDTO.setBolianComId(body.getProjectNo());
        parkInfoDTO.setBolianParkUnionId(parkUnionId);
        String priceDesc = "免费时间:" + body.getFreeTime() + ",第一小时计费:" + body.getMoney()
                + ",周期内最高收费:" + body.getTopMoney();
        parkInfoDTO.setPriceDesc(priceDesc);

        Long id = new SnowflakeIdUtil(new Random().nextInt(9), new Random().nextInt(9)).nextId();
        parkInfoDTO.setId(id);
        String parkImagUrl = StringUtils.join(form.getParkImgUrl().toArray(), ',');
        parkInfoDTO.setParkImgUrl(parkImagUrl);


        String geoHashBinary = GeoHashUtil.getBinary(Double.parseDouble(form.getLongitude()), Double.parseDouble(form.getLatitude()), 32);
        parkInfoDTO.setGeohash(GeoHashUtil.getBase32(geoHashBinary));

        ParkInfo park = new ParkInfo();
        BeanUtils.copyProperties(parkInfoDTO,park);
        int i = parkInfoDao.insert(park);

        //上传泊链停车场信息
        parkToBolian(parkInfoDTO);

        //获取道尔停车场月租规则信息
        monthRulePullService.getMonthRule(parkInfoDTO.getId(), parkInfoDTO.getBolianParkId());
    }

    @Override
    public List<ParkInfoDTO> getNoReservePark() {
        return parkInfoDao.getNoReservePark();
    }



    /**
     *上传泊链停车场信息
     * 处理上传返回信息
     */
    @Async("threadPoolExecutor")
    void parkToBolian(ParkInfoDTO parkInfoDTO){
        try {
            //上传泊链停车场信息
            String parkToBoLian = BolianUtil.addNewParkToBoLian(parkInfoDTO.getId().toString(), parkInfoDTO.getParkName(),
                    parkInfoDTO.getParkAddress(), parkInfoDTO.getTelephone(), parkInfoDTO.getLongitude(), parkInfoDTO.getLatitude(),
                    parkInfoDTO.getTotalParkSpace(), parkInfoDTO.getEmptyParkSpace(), parkInfoDTO.getPriceDesc());

            JsonNode jsonNode = JsonUtil.getJsonNode(parkToBoLian);
            String state = JsonUtil.getJsonValue(jsonNode, "state");
            if ("1".equals(state)) {

                //上传泊链停车场信息 处理返回信息
                addBolianParkResult(parkInfoDTO.getId(), parkToBoLian);
            }
        } catch (Exception e) {
            log.info("上传泊链停车场信息失败");
            e.printStackTrace();
        }
    }

    /**
     * 拉取腾达停车场车辆类型信息
     *
     * @param bolianParkId
     * @return
     */
    @Async("threadPoolExecutor")
    @Transactional
    public Map<String, String> getTengdaParkInfo(String bolianParkId) {
        Map<String, String> map = new HashMap<>();

        ParkInfoDTO park = parkInfoDao.getParkByBolianParkId(bolianParkId);
        if (park == null) {
            ExceptionUtil.businessException("数据库停车场信息未查询到，bolianParkId：+" + bolianParkId);
        }

        List<CarTypes> carTypes = TengdaUtil.getCarTypes(bolianParkId);
        if (carTypes == null || carTypes.size() < 1) {
            ExceptionUtil.businessException("从腾达获取车辆类型信息失败，bolianParkId：+" + bolianParkId);
        }

        //删除规则
        monthRulePullDao.deleteByParkId(park.getId());

        for (CarTypes carType : carTypes) {
            //月租车
            if (carType.getCode() > 80 && carType.getCode() != 91) {
                MonthRulePull pull = new MonthRulePull();
                pull.setParkId(park.getId());
                pull.setMonthType(carType.getCode().toString());
                pull.setDurationType("1");
                pull.setMonthName(carType.getName());
                pull.setParkAmount(new BigDecimal(0));
                pull.setRemark("");
                pull.setParkSource(4);
                pull.setStatus(1);
                monthRulePullDao.insert(pull);
            }
        }
        return map;
    }

}
